#pragma once

#include <QRunnable>
#include <QThreadPool>
#include <entt/entt.hpp>

#include "qlib/all.h"

#include "./components.hpp"

namespace qbe::render::tools {

#define THREAD_NUM 6

struct Task {
  // 多线程操作相关变量
  uint32_t start;
  uint32_t end;
  uint32_t num;
};

// 分割buffer， 用于多线程
template <typename T>
inline void task_assgin(uint32_t size, std::vector<T>* buffers, uint32_t task_num) {
  if (size == 0)
    return;
  uint32_t step = std::ceil(size / task_num);
  step = step > 0 ? step : 1;
  uint32_t num = std::ceil(float(size) / step);
  uint32_t num_small = size % step;
  // SPDLOG_INFO("step: {}, num: {}, num_small: {}, size: {}", step, num, num_small, size);

  buffers->resize(num);
  for (uint32_t i = 0; i < num; i++) {
    uint32_t n = step;
    if ((i + 1) * step > size) {
      n = num_small;
    }
    uint32_t start = i * step;
    uint32_t end = i * step + n;
    (*buffers)[i].start = start;
    (*buffers)[i].end = end;
    (*buffers)[i].num = n;
  }
}

struct PolyItem {
  entt::entity entity;
  qlib::Polygon::s_ptr poly;
  render::TriIndices tri_indices;
};

class TriangleTask : public QRunnable {
 public:
  TriangleTask(std::vector<PolyItem>* items, Task* range) : _items(items), _range(range){};
  ~TriangleTask(){};
  void run() override {
    for (size_t i = _range->start; i < _range->end; i++) {
      auto& it = _items->at(i);
      it.tri_indices = qlib::tools::tri_earcut(it.poly);
    }
  }

 private:
  std::vector<PolyItem>* _items;
  Task* _range;
};

inline void task_polygon_tri(entt::registry& registry) {
  // 使用try_get方法判断Position组件是否存在
  std::vector<PolyItem> items;
  auto view = registry.view<qlib::Polygon::s_ptr>();
  for (auto [e, p] : view.each()) {
    // auto& poly = view.get<qlib::Polygon>(entity);
    items.push_back(PolyItem{e, p});
  }

  // 多线程
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(items.size(), &tasks, THREAD_NUM * 2);
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new TriangleTask(&items, &tasks[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();

  //
  for (auto& it : items) {
    registry.emplace_or_replace<render::TriIndices>(it.entity, it.tri_indices);
  }
}

// ref 多边形三角化任务
inline void task_ref_tri(entt::registry& registry) {
  // 使用try_get方法判断Position组件是否存在
  std::vector<PolyItem> items;
  auto view = registry.view<qlib::Polygon::s_ptr>();
  for (auto [e, p] : view.each()) {
    // auto& poly = view.get<qlib::Polygon>(entity);
    items.push_back(PolyItem{e, p});
  }

  // 多线程
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(items.size(), &tasks, THREAD_NUM * 2);
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new TriangleTask(&items, &tasks[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();

  //
  for (auto& it : items) {
    registry.emplace_or_replace<render::TriIndices>(it.entity, it.tri_indices);
  }
}

/*

--------------Polygon Task ----------------------

*/

class PolygonMeshTask : public QRunnable {
 public:
  PolygonMeshTask(const std::vector<qlib::Polygon::s_ptr>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~PolygonMeshTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i]->points.size();
      total_vertices += size;
      total_indices += size + 2;

      // total_tri_indices += _tri_arr[i]->size();
    }
    _data->vertices = vsg::vec2Array::create(total_vertices + 1);
    _data->indices = vsg::uintArray::create(total_indices);
    // _data->tri_indices = vsg::uintArray::create(total_tri_indices);

    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it->points.size() < 1)
        continue;
      // 顶点、索引
      uint32_t offset_vertices_first = offset_vertices;
      for (size_t i = 0; i < it->points.size(); i++) {
        (*vertices)[offset_vertices++] = vsg::vec2(float(it->points.at(i).x), float(it->points.at(i).y));
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 三角化索引
      // for (auto& id : (*_tri_arr[i])) {
      //   (*tri_indices)[offset_tri_indices++] = id + offset_vertices_first;
      // }
      // 多边形闭合
      (*indices)[offset_indices++] = offset_vertices_first;
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<qlib::Polygon::s_ptr>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_polygon_mesh(std::vector<qlib::Polygon::s_ptr>& polys, std::vector<render::Mesh2D>* meshs) {
  QThreadPool pool;
  pool.setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(polys.size(), &tasks, THREAD_NUM * 2);
  meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new PolygonMeshTask(polys, tasks[i], &(*meshs)[i]);
    pool.start(task);
  }
  pool.waitForDone();
  // QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  // std::vector<Task> tasks;
  // task_assgin(polys.size(), &tasks, THREAD_NUM * 2);
  // meshs->resize(tasks.size());
  // for (int i = 0; i < tasks.size(); i++) {
  //   auto task = new PolygonMeshTask(polys, tasks[i], &(*meshs)[i]);
  //   QThreadPool::globalInstance()->start(task);
  // }
  // QThreadPool::globalInstance()->waitForDone();
};

/*

--------------Polygon Line Task ----------------------

*/

class PolygonLineMeshTask : public QRunnable {
 public:
  PolygonLineMeshTask(const std::vector<qlib::Array<qlib::Vec2d>*>& arr, const Task& task, render::Mesh2D* data)
      : _arr(arr), _task(task), _data(data){};

  ~PolygonLineMeshTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i]->size();
      total_vertices += size;
      total_indices += size + 2;
      // total_tri_indices += _tri_arr[i]->size();
    }
    _data->vertices = vsg::vec2Array::create(total_vertices + 1);
    _data->indices = vsg::uintArray::create(total_indices);
    // _data->tri_indices = vsg::uintArray::create(total_tri_indices);

    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    // auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it->size() < 1)
        continue;
      // 顶点、索引
      uint32_t offset_vertices_first = offset_vertices;
      for (size_t i = 0; i < it->size(); i++) {
        (*vertices)[offset_vertices++] = vsg::vec2(float(it->at(i).x), float(it->at(i).y));
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 三角化索引
      // for (auto& id : (*_tri_arr[i])) {
      //   (*tri_indices)[offset_tri_indices++] = id + offset_vertices_first;
      // }
      // 多边形闭合
      // (*indices)[offset_indices++] = offset_vertices_first;
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<qlib::Vec2dArray*>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_polygon_line_mesh(std::vector<qlib::Vec2dArray*>& polys, std::vector<render::Mesh2D>* meshs) {
  QThreadPool pool;
  pool.setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(polys.size(), &tasks, THREAD_NUM * 2);
  meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new PolygonLineMeshTask(polys, tasks[i], &(*meshs)[i]);
    pool.start(task);
  }
  pool.waitForDone();

  // QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  // std::vector<Task> tasks;
  // task_assgin(polys.size(), &tasks, THREAD_NUM * 2);
  // meshs->resize(tasks.size());
  // for (int i = 0; i < tasks.size(); i++) {
  //   auto task = new PolygonLineMeshTask(polys, tasks[i], &(*meshs)[i]);
  //   QThreadPool::globalInstance()->start(task);
  // }
  // QThreadPool::globalInstance()->waitForDone();
};

/*

--------------Polygon Task ----------------------

*/

class MeshMergeTask : public QRunnable {
 public:
  MeshMergeTask(const std::vector<render::Mesh2D>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~MeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size + 1;
      // total_tri_indices += _tri_arr[i]->size();
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // _data->tri_indices = vsg::uintArray::create(total_tri_indices);

    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      // 顶点、索引
      // uint32_t offset_vertices_first = offset_vertices;

      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // for (size_t i = 0; i < it.vertices->size(); i++) {
      //   (*vertices)[offset_vertices++] = it.vertices->at[i];
      //   (*indices)[offset_indices++] = offset_vertices - 1;
      // }
      // 三角化索引
      // for (auto& id : (*_tri_arr[i])) {
      //   (*tri_indices)[offset_tri_indices++] = id + offset_vertices_first;
      // }
      // 多边形闭合
      // (*indices)[offset_indices++] = offset_vertices_first;
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::Mesh2D>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_mesh_merge(std::vector<render::Mesh2D>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool pool;
  pool.setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new MeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    pool.start(task);
  }
  pool.waitForDone();
};

class LineMeshMergeTask : public QRunnable {
 public:
  LineMeshMergeTask(const std::vector<render::LineMesh>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~LineMeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::LineMesh>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_line_mesh_merge(std::vector<render::LineMesh>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  // QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  // std::vector<Task> tasks;
  // task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  // out_meshs->resize(tasks.size());
  // for (int i = 0; i < tasks.size(); i++) {
  //   auto task = new LineMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
  //   QThreadPool::globalInstance()->start(task);
  // }
  // QThreadPool::globalInstance()->waitForDone();

  QThreadPool pool;
  pool.setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new LineMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    pool.start(task);
  }
  pool.waitForDone();
};

class LineListMeshMergeTask : public QRunnable {
 public:
  LineListMeshMergeTask(const std::vector<render::LineListMesh>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~LineListMeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);

    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    // uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      for (auto v : (*it.vertices)) {
        // (*vertices)[offset_vertices++] = v;
        (*vertices)[offset_vertices] = v;
        (*indices)[offset_indices] = offset_indices;
        offset_vertices++;
        offset_indices++;
      }
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::LineListMesh>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_line_list_mesh_merge(std::vector<render::LineListMesh>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool pool;
  pool.setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new LineListMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    pool.start(task);
  }
  pool.waitForDone();
};

class PolyLineMeshMergeTask : public QRunnable {
 public:
  PolyLineMeshMergeTask(const std::vector<render::PolyLineMesh>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~PolyLineMeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::PolyLineMesh>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_poly_line_mesh_merge(std::vector<render::PolyLineMesh>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool pool;
  pool.setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new PolyLineMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    pool.start(task);
  }
  pool.waitForDone();

  // QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  // std::vector<Task> tasks;
  // task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  // out_meshs->resize(tasks.size());
  // for (int i = 0; i < tasks.size(); i++) {
  //   auto task = new PolyLineMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
  //   QThreadPool::globalInstance()->start(task);
  // }
  // QThreadPool::globalInstance()->waitForDone();
};

class PolyMeshMergeTask : public QRunnable {
 public:
  PolyMeshMergeTask(const std::vector<render::PolyMesh>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~PolyMeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      total_vertices += _arr[i].vertices->size();
      total_indices += _arr[i].indices->size() + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    // auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    // uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      uint32_t offset_vertices_first = offset_vertices;
      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
      }
      // 三角化索引
      for (auto& id : (*it.indices)) {
        (*indices)[offset_indices++] = id + offset_vertices_first;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::PolyMesh>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_poly_mesh_merge(std::vector<render::PolyMesh>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new PolyMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();
};

template <typename T>
class LayoutMeshMergeTask : public QRunnable {
 public:
  LayoutMeshMergeTask(const std::vector<T>& arr, const Task& task, render::Mesh2D* data, bool triangle)
      : _arr(arr), _task(task), _data(data), _triangle(triangle){};

  ~LayoutMeshMergeTask(){};

  void run() override {
    if (_triangle) {
      tri_run();
    } else {
      not_tri_run();
    }
  }

  void not_tri_run() {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;

    for (uint32_t i = _task.start; i < _task.end; i++) {
      total_vertices += _arr[i].vertices.size();
      total_indices += _arr[i].vertices.size() + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices.size() < 1)
        continue;
      for (auto& v : it.vertices) {
        (*vertices)[offset_vertices++] = vsg::vec2{float(v.x), float(v.y)};
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

  void tri_run() {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;

    for (uint32_t i = _task.start; i < _task.end; i++) {
      total_vertices += _arr[i].vertices.size();
      total_indices += _arr[i].vertices.size() + 1;
      total_tri_indices += _arr[i].indices.size() + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    _data->triangle_indices = vsg::uintArray::create(total_tri_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->triangle_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices.size() < 1)
        continue;
      uint32_t offset_vertices_first = offset_vertices;
      for (auto& v : it.vertices) {
        (*vertices)[offset_vertices++] = vsg::vec2{float(v.x), float(v.y)};
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 三角化索引
      for (auto& id : it.indices) {
        (*tri_indices)[offset_tri_indices++] = id + offset_vertices_first;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
      (*tri_indices)[offset_tri_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  bool _triangle{true};
  const std::vector<T>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

template <typename T>
inline void task_layout_mesh_merge(std::vector<T>& in_meshs, std::vector<render::Mesh2D>* out_meshs, bool fill = false) {
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new LayoutMeshMergeTask<T>(in_meshs, tasks[i], &(*out_meshs)[i], fill);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();
};

class LayoutLineMeshMergeTask : public QRunnable {
 public:
  LayoutLineMeshMergeTask(const std::vector<render::LayoutLineMesh>& arr, const Task& task, render::Mesh2D* data)
      : _arr(arr), _task(task), _data(data){};

  ~LayoutLineMeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;

    for (uint32_t i = _task.start; i < _task.end; i++) {
      total_vertices += _arr[i].vertices.size();
      total_indices += _arr[i].vertices.size() + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices.size() < 1)
        continue;
      for (auto& v : it.vertices) {
        (*vertices)[offset_vertices++] = vsg::vec2{float(v.x), float(v.y)};
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::LayoutLineMesh>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_layout_line_mesh_merge(std::vector<render::LayoutLineMesh>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new LayoutLineMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();
};

class LayoutPolyMeshMergeTask : public QRunnable {
 public:
  LayoutPolyMeshMergeTask(const std::vector<render::LayoutPolyMesh>& arr, const Task& task, render::Mesh2D* data)
      : _arr(arr), _task(task), _data(data){};

  ~LayoutPolyMeshMergeTask(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;

    for (uint32_t i = _task.start; i < _task.end; i++) {
      total_vertices += _arr[i].vertices.size();
      total_indices += _arr[i].indices.size() + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices.size() < 1)
        continue;
      uint32_t offset_vertices_first = offset_vertices;
      for (auto& v : it.vertices) {
        (*vertices)[offset_vertices++] = vsg::vec2{float(v.x), float(v.y)};
      }
      // 三角化索引
      for (auto& id : it.indices) {
        (*indices)[offset_indices++] = id + offset_vertices_first;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<render::LayoutPolyMesh>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

inline void task_layout_poly_mesh_merge(std::vector<render::LayoutPolyMesh>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new LayoutPolyMeshMergeTask(in_meshs, tasks[i], &(*out_meshs)[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();
};

template <typename T>
class MeshMergeTaskT : public QRunnable {
 public:
  MeshMergeTaskT(const std::vector<T>& arr, const Task& task, render::Mesh2D* data) : _arr(arr), _task(task), _data(data){};

  ~MeshMergeTaskT(){};

  void run() override {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

 private:
  bool _fill{true};
  const std::vector<T>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

template <typename T>
inline void task_mesh_merge_t(std::vector<T>& in_meshs, std::vector<render::Mesh2D>* out_meshs) {
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new MeshMergeTaskT<T>(in_meshs, tasks[i], &(*out_meshs)[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();
};

template <typename T>
class MeshMergeTaskT2 : public QRunnable {
 public:
  MeshMergeTaskT2(const std::vector<T>& arr, const Task& task, render::Mesh2D* data, bool reset)
      : _arr(arr), _task(task), _data(data), _reset(reset){};

  ~MeshMergeTaskT2(){};

  void run() override {
    if (_reset)
      primitive_reset();
    else
      primitive_no_reset();
  }

  void primitive_reset() {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size + 1;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    uint32_t offset_tri_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
      // 图元重启
      (*indices)[offset_indices++] = 0xffffffff;
    }
  }

  void primitive_no_reset() {
    // 统计顶点数量
    uint32_t total_vertices = 0;
    uint32_t total_indices = 0;
    uint32_t total_tri_vertices = 0;
    uint32_t total_tri_indices = 0;

    auto startIt = _arr.begin() + _task.start;
    auto endIt = _arr.begin() + _task.end;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      uint32_t size = _arr[i].vertices->size();
      total_vertices += size;
      total_indices += size;
    }
    _data->vertices = vsg::vec2Array::create(total_vertices);
    _data->indices = vsg::uintArray::create(total_indices);
    // 组装顶点
    auto& vertices = _data->vertices;
    auto& indices = _data->indices;
    auto& tri_indices = _data->tri_indices;
    uint32_t offset_vertices = 0;
    uint32_t offset_indices = 0;
    for (uint32_t i = _task.start; i < _task.end; i++) {
      auto& it = _arr[i];
      if (it.vertices->size() < 1)
        continue;
      for (auto v : (*it.vertices)) {
        (*vertices)[offset_vertices++] = v;
        (*indices)[offset_indices++] = offset_vertices - 1;
      }
    }
  }

 private:
  bool _fill{true};
  bool _reset{true};
  const std::vector<T>& _arr;
  const Task& _task;
  render::Mesh2D* _data;
};

template <typename T>
inline void task_mesh_merge_t2(std::vector<T>& in_meshs, std::vector<render::Mesh2D>* out_meshs, bool primitive_reset = true) {
  QThreadPool::globalInstance()->setMaxThreadCount(THREAD_NUM);
  std::vector<Task> tasks;
  task_assgin(in_meshs.size(), &tasks, THREAD_NUM * 2);
  out_meshs->resize(tasks.size());
  for (int i = 0; i < tasks.size(); i++) {
    auto task = new MeshMergeTaskT2<T>(in_meshs, tasks[i], &(*out_meshs)[i]);
    QThreadPool::globalInstance()->start(task);
  }
  QThreadPool::globalInstance()->waitForDone();
};

}  // namespace qbe::render::tools